🌎 rns.kin.earth git 🌍
Commit 64749b4d18d62e810f4d11eb71fe01f049ef53fa
Parents : 875d8ef
Author : Mark Qvist <bc7291552be7a58f361522990465165c>
Date : 2026-05-18T01:24:15+02:00
Cleanup. Prepared artifact fetch.
Changes
Diff
diff --git a/RNS/Utilities/rngit/server.py b/RNS/Utilities/rngit/server.py
index f138e4cc..df5ca54d 100644
--- a/RNS/Utilities/rngit/server.py
+++ b/RNS/Utilities/rngit/server.py
@@ -86,6 +86,7 @@ def program_setup(configdir, rnsconfigdir=None, verbosity=0, quietness=0, servic
git_client = ReticulumGitClient(configdir=configdir, verbosity=targetverbosity, identitypath=identity)
if operation == "list": git_client.list_releases(remote=task["remote"])
elif operation == "view": git_client.view_release(remote=task["remote"], target=task["target"])
+ elif operation == "fetch": git_client.fetch_release(remote=task["remote"], target=task["target"])
elif operation == "create": git_client.create_release(remote=task["remote"], target=task["target"], signer=task["signer"], name=task["name"])
elif operation == "delete": git_client.delete_release(remote=task["remote"], target=task["target"])
elif operation == "latest": git_client.latest_release(remote=task["remote"], target=task["target"])
@@ -161,7 +162,7 @@ def main():
parser.add_argument("-s", "--signer", action="store", metavar="PATH", default=None, help="path to signing identity, if different from release identity", type=str)
parser.add_argument("-n", "--name", action="store", metavar="name", default=None, help="package name if different from repo name", type=str)
parser.add_argument("repository", nargs="?", default=None, help="URL of remote repository", type=str)
- parser.add_argument("operation", nargs="?", default=None, help="list, view, create, latest or delete", type=str)
+ parser.add_argument("operation", nargs="?", default=None, help="list, view, fetch, create, latest or delete", type=str)
parser.add_argument("target", nargs="?", default=None, help="tag and path to release artifacts directory", type=str)
elif subcommand == "perms":
@@ -524,7 +525,7 @@ class ReticulumGitClient():
#########################
def create_repository(self, remote=None):
- if not remote: print(f"No remote specified"); exit(1)
+ if not remote: self.abort(f"No remote specified")
self.connect_remote(remote)
timeout = self.link_timeout
@@ -565,13 +566,13 @@ class ReticulumGitClient():
####################
def fork_repository(self, source=None, target=None):
- if not source: print(f"No source specified"); exit(1)
- if not target: print(f"No target specified"); exit(1)
+ if not source: self.abort(f"No source specified")
+ if not target: self.abort(f"No target specified")
self._remote_clone_operation(source, target, self.PATH_FORK, "fork")
def mirror_repository(self, source=None, target=None):
- if not source: print(f"No source specified"); exit(1)
- if not target: print(f"No target specified"); exit(1)
+ if not source: self.abort(f"No source specified")
+ if not target: self.abort(f"No target specified")
self._remote_clone_operation(source, target, self.PATH_MIRROR, "mirror")
def _resolve_aliased_url(self, url):
@@ -627,7 +628,7 @@ class ReticulumGitClient():
if self.link: self.link.teardown()
def sync_repository(self, remote=None):
- if not remote: print(f"No remote specified"); exit(1)
+ if not remote: self.abort(f"No remote specified")
self.connect_remote(remote)
timeout = self.link_timeout
@@ -717,7 +718,7 @@ class ReticulumGitClient():
return None
def list_releases(self, remote=None):
- if not remote: print(f"No remote specified"); exit(1)
+ if not remote: self.abort(f"No remote specified")
self.connect_remote(remote)
timeout = self.link_timeout
@@ -775,8 +776,8 @@ class ReticulumGitClient():
if self.link: self.link.teardown()
def view_release(self, remote=None, target=None):
- if not remote: print(f"No remote specified"); exit(1)
- if not target: print(f"No target specified"); exit(1)
+ if not remote: self.abort(f"No remote specified")
+ if not target: self.abort(f"No target specified")
self.connect_remote(remote)
timeout = self.link_timeout
@@ -833,17 +834,56 @@ class ReticulumGitClient():
finally:
if self.link: self.link.teardown()
+ def fetch_release(self, remote=None, target=None):
+ if not remote: self.abort(f"No remote specified")
+ if not target: self.abort(f"No target specified")
+ self.connect_remote(remote)
+
+ timeout = self.link_timeout
+ while not self.link_ready and not self.link_failed and timeout > 0:
+ time.sleep(self.wait_sleep)
+ timeout -= self.wait_sleep
+
+ if not self.link_ready: self.abort("Link establishment failed")
+
+ try:
+ destination_hash, group, repo = self.parse_remote_url(remote)
+ repo_path = f"{group}/{repo}"
+
+ parts = target.split(":")
+ if len(parts) < 2: self.abort("Invalid release specification")
+ tag = parts[0]
+ artifact = parts[1]
+
+ def fetch(name):
+ request_data = {self.IDX_REPOSITORY: repo_path, "operation": "fetch", "tag": tag, "artifact": name}
+ response, metadata = self.send_request(self.PATH_RELEASE, request_data, timeout=30)
+ print("\r \r", end="")
+ if not response or not isinstance(response, bytes): self.abort("No response from remote")
+ status_byte = response[0]
+ if status_byte != 0:
+ error_msg = response[1:].decode("utf-8", errors="ignore")
+ self.abort(f"Remote error: {error_msg}")
+ if len(response) <= 1: self.abort("Empty response from remote")
+ print()
+
+ # TODO: Implement
+
+ except Exception as e: self.abort(f"Error viewing release: {e}")
+ finally:
+ if self.link: self.link.teardown()
+
def create_release(self, remote=None, target=None, signer=None, name=None):
if signer:
try:
identity_path = os.path.expanduser(signer)
- if not os.path.isfile(identity_path): print(f"Signer identity {identity_path} does not exist"); exit(1)
+ if not os.path.isfile(identity_path): self.abort(f"Signer identity {identity_path} does not exist")
else: signer = RNS.Identity.from_file(signer)
- if not signer: print(f"Could not load signer identity from {identity_path}"); exit(1)
- except Exception as e: print(f"Could not load signer identity from {identity_path}: {e}"); exit(1)
+ if not signer: self.abort(f"Could not load signer identity from {identity_path}")
+ except Exception as e: self.abort(f"Could not load signer identity from {identity_path}: {e}")
- if not remote: print(f"No remote specified"); exit(1)
- if not target: print(f"No target specified"); exit(1)
+ if not remote: self.abort(f"No remote specified")
+ if not target: self.abort(f"No target specified")
if not signer: signer = self.identity
self.connect_remote(remote)
@@ -861,15 +901,11 @@ class ReticulumGitClient():
release_time = int(time.time())
release_time_iso = datetime.fromtimestamp(release_time, tz=timezone.utc).isoformat().replace("+00:00", "Z")
- # Parse target - can be:
- # 1. Just a tag name: "v1.0.0"
- # 3. Tag with path to artifacts directory: "v1.0.0:/path/to/artifacts"
-
parts = target.split(":")
if len(parts) < 2: self.abort("Invalid release specification\nDid you provide both a tag and artifacts path such as \"1.0.0:./dist\"?")
tag = parts[0]
artifacts_path = os.path.expanduser(parts[1])
- commit_hash = ""
+ commit_hash = None # TODO: Get commit hash from tag
if not os.path.isdir(artifacts_path): self.abort("Specified artifacts directory does not exist")
artifacts = [f for f in os.listdir(artifacts_path) if os.path.isfile(os.path.join(artifacts_path, f))]
@@ -882,8 +918,8 @@ class ReticulumGitClient():
# Generate manifest
package_name = name or repo
- manifest_meta = {"name": package_name ,"version": tag, "released": release_time_iso,
- "timestamp": release_time, "artifacts": []}
+ manifest_meta = {"name": package_name ,"version": tag, "released": release_time_iso, "timestamp": release_time,
+ "origin": destination_hash, "commit": commit_hash, "artifacts": []}
try:
manifest_path = artifacts_path+f"/manifest.{self.MSG_EXT}"
for artifact in artifacts:
@@ -902,7 +938,7 @@ class ReticulumGitClient():
manifest = create_rsg(signer, notes, embed=True, meta=manifest_meta)
with open(manifest_path, "wb") as fh: fh.write(manifest)
- except Exception as e: print(f"Release manifest generation failed: {e}"); exit(1)
+ except Exception as e: self.abort(f"Release manifest generation failed: {e}")
# Step 1: Initialize release
print("Initializing release on remote...")
@@ -967,8 +1003,8 @@ class ReticulumGitClient():
if self.link: self.link.teardown()
def delete_release(self, remote=None, target=None):
- if not remote: print(f"No remote specified"); exit(1)
- if not target: print(f"No target specified"); exit(1)
+ if not remote: self.abort(f"No remote specified")
+ if not target: self.abort(f"No target specified")
self.connect_remote(remote)
timeout = self.link_timeout
@@ -1010,8 +1046,8 @@ class ReticulumGitClient():
if self.link: self.link.teardown()
def latest_release(self, remote=None, target=None):
- if not remote: print(f"No remote specified"); exit(1)
- if not target: print(f"No target specified"); exit(1)
+ if not remote: self.abort(f"No remote specified")
+ if not target: self.abort(f"No target specified")
self.connect_remote(remote)
timeout = self.link_timeout
@@ -1057,7 +1093,7 @@ class ReticulumGitClient():
##########################
def group_permissions(self, remote=None):
- if not remote: print(f"No remote specified"); exit(1)
+ if not remote: self.abort(f"No remote specified")
self.connect_remote(remote)
timeout = self.link_timeout
@@ -1107,7 +1143,7 @@ class ReticulumGitClient():
if self.link: self.link.teardown()
def repository_permissions(self, remote=None):
- if not remote: print(f"No remote specified"); exit(1)
+ if not remote: self.abort(f"No remote specified")
self.connect_remote(remote)
timeout = self.link_timeout
@@ -1163,7 +1199,7 @@ class ReticulumGitClient():
########################
def work_list(self, remote=None, scope="active"):
- if not remote: print(f"No remote specified"); exit(1)
+ if not remote: self.abort(f"No remote specified")
self.connect_remote(remote)
timeout = self.link_timeout
@@ -1220,8 +1256,8 @@ class ReticulumGitClient():
if self.link: self.link.teardown()
def work_view(self, remote=None, doc_id=None, scope="active"):
- if not remote: print(f"No remote specified"); exit(1)
- if doc_id is None: print(f"No document ID specified"); exit(1)
+ if not remote: self.abort(f"No remote specified")
+ if doc_id is None: self.abort(f"No document ID specified")
self.connect_remote(remote)
timeout = self.link_timeout
@@ -1295,8 +1331,8 @@ class ReticulumGitClient():
if self.link: self.link.teardown()
def work_create(self, remote=None, title=None):
- if not remote: print(f"No remote specified"); exit(1)
- if not title: print(f"No title specified"); exit(1)
+ if not remote: self.abort(f"No remote specified")
+ if not title: self.abort(f"No title specified")
self.connect_remote(remote)
timeout = self.link_timeout
@@ -1340,8 +1376,8 @@ class ReticulumGitClient():
if self.link: self.link.teardown()
def work_propose(self, remote=None, title=None):
- if not remote: print(f"No remote specified"); exit(1)
- if not title: print(f"No title specified"); exit(1)
+ if not remote: self.abort(f"No remote specified")
+ if not title: self.abort(f"No title specified")
self.connect_remote(remote)
timeout = self.link_timeout
@@ -1385,8 +1421,8 @@ class ReticulumGitClient():
if self.link: self.link.teardown()
def work_edit(self, remote=None, doc_id=None, title=None, scope="active"):
- if not remote: print(f"No remote specified"); exit(1)
- if doc_id is None: print(f"No document ID specified"); exit(1)
+ if not remote: self.abort(f"No remote specified")
+ if doc_id is None: self.abort(f"No document ID specified")
self.connect_remote(remote)
timeout = self.link_timeout
@@ -1439,8 +1475,8 @@ class ReticulumGitClient():
if self.link: self.link.teardown()
def work_delete(self, remote=None, doc_id=None, scope="active"):
- if not remote: print(f"No remote specified"); exit(1)
- if doc_id is None: print(f"No document ID specified"); exit(1)
+ if not remote: self.abort(f"No remote specified")
+ if doc_id is None: self.abort(f"No document ID specified")
self.connect_remote(remote)
timeout = self.link_timeout
@@ -1479,8 +1515,8 @@ class ReticulumGitClient():
if self.link: self.link.teardown()
def work_comment(self, remote=None, doc_id=None, scope="active"):
- if not remote: print(f"No remote specified"); exit(1)
- if doc_id is None: print(f"No document ID specified"); exit(1)
+ if not remote: self.abort(f"No remote specified")
+ if doc_id is None: self.abort(f"No document ID specified")
self.connect_remote(remote)
timeout = self.link_timeout
@@ -1522,8 +1558,8 @@ class ReticulumGitClient():
if self.link: self.link.teardown()
def work_complete(self, remote=None, doc_id=None):
- if not remote: print(f"No remote specified"); exit(1)
- if doc_id is None: print(f"No document ID specified"); exit(1)
+ if not remote: self.abort(f"No remote specified")
+ if doc_id is None: self.abort(f"No document ID specified")
self.connect_remote(remote)
timeout = self.link_timeout
@@ -1561,8 +1597,8 @@ class ReticulumGitClient():
if self.link: self.link.teardown()
def work_activate(self, remote=None, doc_id=None):
- if not remote: print(f"No remote specified"); exit(1)
- if doc_id is None: print(f"No document ID specified"); exit(1)
+ if not remote: self.abort(f"No remote specified")
+ if doc_id is None: self.abort(f"No document ID specified")
self.connect_remote(remote)
timeout = self.link_timeout
@@ -1600,8 +1636,8 @@ class ReticulumGitClient():
if self.link: self.link.teardown()
def work_permissions(self, remote=None, doc_id=None):
- if not remote: print(f"No remote specified"); exit(1)
- if doc_id is None: print(f"No document ID specified"); exit(1)
+ if not remote: self.abort(f"No remote specified")
+ if doc_id is None: self.abort(f"No document ID specified")
self.connect_remote(remote)
timeout = self.link_timeout
Served by rngit 1.5.2 - Generated in 0.05s